package cn.cttic.order.dubbo;

import cn.cttic.common.core.exception.order.OrderException;
import cn.cttic.common.core.utils.BeanCopyUtils;
import cn.cttic.order.api.RemoteReconciliationService;
import cn.cttic.order.api.domain.BaseInstallOrder;
import cn.cttic.order.api.domain.BaseReconciliation;
import cn.cttic.order.api.domain.BaseReconciliationDetail;
import cn.cttic.order.api.domain.BaseSaleOrder;
import cn.cttic.order.api.domain.vo.BaseReconciliationDetailReaderVo;
import cn.cttic.order.api.domain.vo.BaseReconciliationDetailVo;
import cn.cttic.order.mapper.BaseInstallOrderMapper;
import cn.cttic.order.mapper.BaseReconciliationDetailMapper;
import cn.cttic.order.mapper.BaseReconciliationMapper;
import cn.cttic.order.mapper.BaseSaleOrderMapper;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.prometheus.client.Collector;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@DubboService
@Slf4j
@RequiredArgsConstructor
public class RemoteReconciliationServiceImpl implements RemoteReconciliationService {

    private final BaseReconciliationMapper baseReconciliationMapper;

    private final BaseReconciliationDetailMapper baseReconciliationDetailMapper;

    private final BaseSaleOrderMapper baseSaleOrderMapper;

    private final BaseInstallOrderMapper baseInstallOrderMapper;

    private String generateReconciliationId(int reconciliationIdSeq) {
        return "HX" + DateUtil.format(new Date(), "yyMMddHHmm") + String.format("%05d", reconciliationIdSeq);
    }

    /**
     * 创建上月销售订单对账单
     *
     * @return
     */
    @Override
    public int createLastMonthSaleOrderReconciliationBill() {

        LocalDate lastMonth = LocalDate.now().minusMonths(1).with(TemporalAdjusters.firstDayOfMonth()).plusDays(1);

        var lst = baseReconciliationMapper.selectList(
            new LambdaQueryWrapper<BaseReconciliation>()
                .eq(BaseReconciliation::getOrderType, "销售")
                .ge(BaseReconciliation::getPeriodBeginDate, lastMonth.atTime(LocalTime.MIN))
                .le(BaseReconciliation::getPeriodEndDate, lastMonth.atTime(LocalTime.MIN))
        );
        if (lst.size() > 0) {
            return -1;
        }

        int reconciliationIdSeq = baseReconciliationMapper.selectCount(new LambdaQueryWrapper<BaseReconciliation>()).intValue() + 1;
        String reconciliationId = generateReconciliationId(reconciliationIdSeq);

        LocalDateTime lastMonthBeginDate = lastMonth.with(TemporalAdjusters.firstDayOfMonth()).atTime(LocalTime.MIN);
        LocalDateTime lastMonthEndDate = lastMonth.with(TemporalAdjusters.lastDayOfMonth()).atTime(LocalTime.MAX);

        QueryWrapper qw = new QueryWrapper();
        qw.ge("bso.create_time", lastMonthBeginDate);
        qw.le("bso.create_time", lastMonthEndDate);
        List<BaseReconciliationDetailReaderVo> baseSaleOrders = baseReconciliationMapper.getSaleOrderReconciliationList(qw);

        Map<String, List<BaseReconciliationDetailReaderVo>> saleOrderMap = baseSaleOrders.stream().collect(Collectors.groupingBy(BaseReconciliationDetailReaderVo::getCompanyId));
        for (String key : saleOrderMap.keySet()) {
            List<BaseReconciliationDetailReaderVo> saleOrderList = saleOrderMap.get(key);
            if (saleOrderList.size() > 0) {
                List<BaseReconciliationDetail> toInsertDetailList = new ArrayList<>();
                for (BaseReconciliationDetailReaderVo saleOrder : saleOrderList) {
                    BaseReconciliationDetail baseReconciliationDetail = BeanCopyUtils.copy(saleOrder, BaseReconciliationDetail.class);
                    baseReconciliationDetail.setReconciliationId(reconciliationId);
                    toInsertDetailList.add(baseReconciliationDetail);
                }
                baseReconciliationDetailMapper.insertBatch(toInsertDetailList);

                BaseReconciliation reconciliation = new BaseReconciliation();
                reconciliation.setId(reconciliationId);
                reconciliation.setCompanyId(saleOrderList.get(0).getCompanyId());
                reconciliation.setPeriodBeginDate(lastMonthBeginDate);
                reconciliation.setPeriodEndDate(lastMonthEndDate);
                reconciliation.setOrderType("销售");
                reconciliation.setOrderCount(toInsertDetailList.size());
                reconciliation.setReconciliationStatus(0);
                baseReconciliationMapper.insert(reconciliation);

                reconciliationIdSeq ++;
                reconciliationId = generateReconciliationId(reconciliationIdSeq);
            }
        }

        return 0;
    }

    /**
     * 创建上月安装订单对账单
     *
     * @return
     */
    @Override
    public int createLastMonthInstallOrderReconciliationBill() {

        LocalDate lastMonth = LocalDate.now().minusMonths(1).with(TemporalAdjusters.firstDayOfMonth()).plusDays(1);

        var lst = baseReconciliationMapper.selectList(
            new LambdaQueryWrapper<BaseReconciliation>()
                .eq(BaseReconciliation::getOrderType, "安装")
                .ge(BaseReconciliation::getPeriodBeginDate, lastMonth.atTime(LocalTime.MIN))
                .le(BaseReconciliation::getPeriodEndDate, lastMonth.atTime(LocalTime.MIN))
        );
        if (lst.size() > 0) {
            return -1;
        }

        int reconciliationIdSeq = baseReconciliationMapper.selectCount(new LambdaQueryWrapper<BaseReconciliation>()).intValue() + 1;
        String reconciliationId = generateReconciliationId(reconciliationIdSeq);

        LocalDateTime lastMonthBeginDate = lastMonth.with(TemporalAdjusters.firstDayOfMonth()).atTime(LocalTime.MIN);
        LocalDateTime lastMonthEndDate = lastMonth.with(TemporalAdjusters.lastDayOfMonth()).atTime(LocalTime.MAX);

        QueryWrapper qw = new QueryWrapper();
        qw.ge("bso.create_time", lastMonthBeginDate);
        qw.le("bso.create_time", lastMonthEndDate);
        List<BaseReconciliationDetailReaderVo> baseSaleOrders = baseReconciliationMapper.getInstallOrderReconciliationList(qw);

        Map<String, List<BaseReconciliationDetailReaderVo>> saleOrderMap = baseSaleOrders.stream().collect(Collectors.groupingBy(BaseReconciliationDetailReaderVo::getCompanyId));
        for (String key : saleOrderMap.keySet()) {
            List<BaseReconciliationDetailReaderVo> saleOrderList = saleOrderMap.get(key);
            if (saleOrderList.size() > 0) {
                List<BaseReconciliationDetail> toInsertDetailList = new ArrayList<>();
                for (BaseReconciliationDetailReaderVo saleOrder : saleOrderList) {
                    BaseReconciliationDetail baseReconciliationDetail = BeanCopyUtils.copy(saleOrder, BaseReconciliationDetail.class);
                    baseReconciliationDetail.setReconciliationId(reconciliationId);
                    toInsertDetailList.add(baseReconciliationDetail);
                }
                baseReconciliationDetailMapper.insertBatch(toInsertDetailList);

                BaseReconciliation reconciliation = new BaseReconciliation();
                reconciliation.setId(reconciliationId);
                reconciliation.setCompanyId(saleOrderList.get(0).getCompanyId());
                reconciliation.setPeriodBeginDate(lastMonthBeginDate);
                reconciliation.setPeriodEndDate(lastMonthEndDate);
                reconciliation.setOrderType("安装");
                reconciliation.setOrderCount(toInsertDetailList.size());
                reconciliation.setReconciliationStatus(0);
                baseReconciliationMapper.insert(reconciliation);

                reconciliationIdSeq ++;
                reconciliationId = generateReconciliationId(reconciliationIdSeq);
            }
        }

        return 0;
    }

}
